#pragma once 
#include "Channel.hpp"
#include "Task.hpp"
#include <vector>
#include <unistd.h>
#include <sys/wait.h>

enum{
    OK = 0,
    PIPEERROR,
    FORKERROR
};
void Worker(){
    // sleep(2);
    while(true){
        int task = 0;
        ssize_t n = ::read(0,&task,sizeof(task));
        if (n > 0){
            tm.Excute(task);
        }
        else if(n == 0){
            break;
        }
        else{
            //等待失败
            perror("子进程获取任务失败");
            return;
        }
        // sleep(1)
    }
}
class ProcessPool
{
public:
    ProcessPool(int ProcessNum = 0)
        :_pronum(ProcessNum)
        {}
    // 创建管道和子进程
    void InitProcessPool(){
        for (int i = 0; i < _pronum; i++){
            int PipeFds[2] = {0};
            int n = pipe(PipeFds);
            if (n < 0){
                perror("create pipe error");
                exit(PIPEERROR);
            }
            pid_t fd = fork();
            if (fd > 0){
                //父进程
                ::close(PipeFds[0]); //关闭读端
                // Channel ch(PipeFds[1],fd);
                _Channels.emplace_back(PipeFds[1],fd);
            }
            else if(fd == 0){
                //子进程
                ::close(PipeFds[1]); //关闭写端
                //关闭历史的读端
                std::cout << "关闭历史的fd: ";
                for (auto& c : _Channels){
                    std::cout << c.Wfd() << " ";
                    c.Close();
                }
                std::cout <<std::endl;
                ::dup2(PipeFds[0],0); //让子进程统一从标准输入中获取数据
                Worker();
                ::close(PipeFds[0]);
                exit(OK);
            }
            else {
                perror("fork error");
                exit(FORKERROR);
            }
        }
    }
    void DebugPrint(){
        for (auto& c : _Channels){
            std::cout << c.Name() << std::endl;
        }
    }
    void Wait(){
        //version 3
        for (auto& c : _Channels){
            c.Close();
            pid_t rid = ::waitpid(c.Who(),nullptr,0);
            if (rid > 0){
                std::cout << "wait child: " << c.Who() << "success..." <<std::endl;
            }            
        }        
        //version 2
        // for (int i = _Channels.size()-1; i >= 0; i--){
        //     _Channels[i].Close();
        //     pid_t rid = ::waitpid(_Channels[i].Who(),nullptr,0);
        //     if (rid > 0){
        //         std::cout << "wait child: " <<_Channels[i].Who() << "success..." << std::endl;
        //     }
        // }

        //version 1
        // for (auto& c : _Channels){
        //     c.Close();
        // }
        // for (auto& c : _Channels){
        //     pid_t rid = ::waitpid(c.Who(),nullptr,0);
        //     if (rid > 0){
        //         std::cout << "wait child: " << c.Who() << "success..." << std::endl;
        //     }
        // }
    }
    //分派任务
    void Dispacher()
    {
        int total = 10;
        int who = 0;
        while(total--)
        {
            //选择一个进程
            int pro = (who++) % _Channels.size();            
            who %= _Channels.size();
            //选择一个任务
            int cmd = tm.SelectTask();
            //派发任务
            std::cout << _Channels[pro].Name() << "正在执行任务 "<<cmd << ",还剩下: " << total << "个任务" << std::endl; 
            _Channels[pro].Send(cmd);
            sleep(1);
        }
    }
    ~ProcessPool(){}
private:
    int _pronum;
    std::vector<Channel> _Channels;
};